﻿using System;
using System.Diagnostics;
using System.Linq.Functional;

namespace SoftSource.Common
{
    /// <summary>
    /// These extension attempt to safely invoke delegates
    /// </summary>
    public static class InvocationExtensions
    {
        #region Actions
        public static void TryInvoke(this Action action)
        {
            if (action != null)
                action();
        }

        public static void TryInvoke<TArg>(this Action<TArg> action, TArg arg)
        {
            if (action != null)
                action.CurryAll()(arg).TryInvoke();
        }

        public static void TryInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> action, TArg1 arg1, TArg2 arg2)
        {
            if (action != null)
                action.CurryAll()(arg1, arg2).TryInvoke();
        }

        public static void TryInvoke<TArg1, TArg2, TArg3>(this Action<TArg1, TArg2, TArg3> action, TArg1 arg1, TArg2 arg2, TArg3 arg3)
        {
            if (action != null)
                action.CurryAll()(arg1, arg2, arg3).TryInvoke();
        }

        public static void TryInvoke<TArg1, TArg2, TArg3, TArg4>(this Action<TArg1, TArg2, TArg3, TArg4> action, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
        {
            if (action != null)
                action.CurryAll()(arg1, arg2, arg3, arg4).TryInvoke();
        }
        #endregion

        #region Funcs
        public static TResult TryInvoke<TResult>(this Func<TResult> func)
        {
            if (func != null)
                return func();

            return default(TResult);
        }

        public static TResult TryInvoke<TArg, TResult>(this Func<TArg, TResult> func, TArg arg)
        {
            if (func != null)
                return func.CurryAll()(arg).TryInvoke();

            return default(TResult);
        }

        public static TResult TryInvoke<TArg1, TArg2, TResult>(this Func<TArg1, TArg2, TResult> func, TArg1 arg1, TArg2 arg2)
        {
            if (func != null)
                return func.CurryAll()(arg1, arg2).TryInvoke();

            return default(TResult);
        }

        public static TResult TryInvoke<TArg1, TArg2, TArg3, TResult>(this Func<TArg1, TArg2, TArg3, TResult> func, TArg1 arg1, TArg2 arg2, TArg3 arg3)
        {
            if (func != null)
                return func.CurryAll()(arg1, arg2, arg3).TryInvoke();

            return default(TResult);
        }

        public static TResult TryInvoke<TArg1, TArg2, TArg3, TArg4, TResult>(this Func<TArg1, TArg2, TArg3, TArg4, TResult> func, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
        {
            if (func != null)
                return func.CurryAll()(arg1, arg2, arg3, arg4).TryInvoke();

            return default(TResult);
        }
        #endregion
    }
}
